package com.jinmdz.fmis.api.wrapper;

import com.jinmdz.fmis.api.constant.CacheKey;
import com.jinmdz.fmis.common.util.BeanUtil;
import com.jinmdz.fmis.common.util.DataUtil;
import com.jinmdz.fmis.common.util.ReflectUtil;
import com.jinmdz.fmis.core.annotation.AnDict;
import com.jinmdz.fmis.core.base.BaseBean;
import com.jinmdz.fmis.core.constant.EDictCode;
import com.jinmdz.fmis.core.util.CacheUtil;
import com.jinmdz.fmis.dao.dao.DataDictionaryDao;
import com.jinmdz.fmis.dao.model.dictionary.DataDictionaryItem;
import org.springframework.cache.Cache;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Dictionary封装处理类
 *
 * @author LiCongLu
 * @date 2020-01-14 13:42
 */
@Component
public class DictionaryWrapper {

    @Resource
    private DataDictionaryDao dataDictionaryDao;

    @Resource
    private Cache dictionaryCache;

    /**
     * Bean初始化函数
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-01-14 13:46
     */
    @PostConstruct
    public void initMethod() {
        refreshDictionary();
    }

    /**
     * Bean销毁函数
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-01-19 11:17
     */
    @PreDestroy
    public void destroyMethod() {
        synchronized (dictionaryCache) {
            // 清除原有缓存
            CacheUtil.clearCacheValue(dictionaryCache, CacheKey.DATA_DICTIONARY);
        }
    }

    /**
     * 刷新数据字典缓存
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-01-14 13:45
     */
    public void refreshDictionary() {
        // 加载新字典数据，刷新
        ArrayList<DataDictionaryItem> dictList = dataDictionaryDao.listAllDataDictionaryItem();
        HashMap<String, ArrayList<DataDictionaryItem>> dictMap = new HashMap<>(16);
        ArrayList<DataDictionaryItem> deletedList = new ArrayList<>();

        // 遍历节点
        for (EDictCode codeEnum : EDictCode.values()) {
            if (codeEnum.getCode() == null || codeEnum.getCode().length() == 0) {
                continue;
            }

            // 屏蔽掉家属及承办人性别
            if (EDictCode.SEX_SIMPLE == codeEnum) {
                continue;
            }

            String dictCode = codeEnum.getCode();
            ArrayList<DataDictionaryItem> dictItems = new ArrayList<>();
            if (dictMap.containsKey(dictCode)) {
                dictItems = dictMap.get(dictCode);
            } else {
                dictMap.put(dictCode, dictItems);
            }

            // 获取新字典
            for (DataDictionaryItem item : dictList) {
                // 剔除被删除的字典
                if (DataUtil.valid(item.getDeleted())) {
                    if (!deletedList.contains(item)) {
                        deletedList.add(item);
                    }
                    continue;
                }

                if (dictCode.equals(item.getDictCode())) {
                    dictItems.add(item);
                }
            }
        }

        // 单独处理性别
        ArrayList<DataDictionaryItem> sexItems = dictMap.get(EDictCode.SEX.getCode());
        ArrayList<DataDictionaryItem> simpleItems = new ArrayList<>();
        for (DataDictionaryItem item : sexItems) {
            if (item.getDataValue().intValue() > 0) {
                simpleItems.add(BeanUtil.copy2Bean(item, new DataDictionaryItem()));
            }
        }
        dictMap.put(EDictCode.SEX_SIMPLE.getCode(), simpleItems);

        // 添加同步锁，其有效性有待测试
        synchronized (dictionaryCache) {
            // 清除原有缓存
            CacheUtil.clearCacheValue(dictionaryCache, CacheKey.DATA_DICTIONARY);
            CacheUtil.clearCacheValue(dictionaryCache, CacheKey.DATA_DICTIONARY_ALL);
            CacheUtil.clearCacheValue(dictionaryCache, CacheKey.DATA_DICTIONARY_DELETED);
            dictionaryCache.put(CacheKey.DATA_DICTIONARY, dictMap);
            dictionaryCache.put(CacheKey.DATA_DICTIONARY_ALL, deletedList);
            dictionaryCache.put(CacheKey.DATA_DICTIONARY_DELETED, deletedList);
        }
    }

    /**
     * 获取缓存字典
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-01-14 15:07
     */
    public HashMap<String, ArrayList<DataDictionaryItem>> mapDictionary() {
        HashMap<String, ArrayList<DataDictionaryItem>> dictMap = new HashMap<>(16);
        synchronized (dictionaryCache) {
            HashMap<String, ArrayList<DataDictionaryItem>> cacheMap = CacheUtil.getCacheValue(dictionaryCache, CacheKey.DATA_DICTIONARY);
            if (cacheMap != null && cacheMap.size() > 0) {
                dictMap = cacheMap;
            }
        }
        return dictMap;
    }

    /**
     * 获取删除字典集合
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-05-16 10:31
     */
    public ArrayList<DataDictionaryItem> deletedDictionary() {
        ArrayList<DataDictionaryItem> dictList = new ArrayList<>();
        synchronized (dictionaryCache) {
            ArrayList<DataDictionaryItem> cacheDeleted = CacheUtil.getCacheValue(dictionaryCache, CacheKey.DATA_DICTIONARY_DELETED);
            if (cacheDeleted != null && cacheDeleted.size() > 0) {
                dictList = cacheDeleted;
            }
        }
        return dictList;
    }

    /**
     * 设置数据字典文本
     *
     * @param bean 需要设置的数据
     * @return
     * @author LiCongLu
     * @date 2020-01-14 16:00
     */
    public <T extends BaseBean> void resetDataText(T bean) {
        if (bean != null) {
            HashMap<String, Field> fieldMap = ReflectUtil.getFieldMapByClass(bean.getClass());
            resetDataText4Bean(mapDictionary(), deletedDictionary(), fieldMap, bean);
        }
    }

    /**
     * 设置数据字典文本
     *
     * @param beanList 数据集合
     * @return
     * @author LiCongLu
     * @date 2020-01-14 17:17
     */
    public <T extends BaseBean> void resetDataText(List<T> beanList) {
        if (beanList != null && beanList.size() > 0) {
            HashMap<String, ArrayList<DataDictionaryItem>> dictMap = mapDictionary();
            ArrayList<DataDictionaryItem> deletedList = deletedDictionary();
            HashMap<String, Field> fieldMap = ReflectUtil.getFieldMapByClass(beanList.get(0).getClass());
            for (T bean : beanList) {
                resetDataText4Bean(dictMap, deletedList, fieldMap, bean);
            }
        }
    }

    /**
     * 设置数据字典文本
     *
     * @param dictMap     缓存字典数据
     * @param deletedList 删除字典数据
     * @param fieldMap    反射属性
     * @param bean        对象
     * @return
     * @author LiCongLu
     * @date 2020-01-14 16:01
     */
    private <T> void resetDataText4Bean(HashMap<String, ArrayList<DataDictionaryItem>> dictMap, ArrayList<DataDictionaryItem> deletedList, HashMap<String, Field> fieldMap, T bean) {
        for (Map.Entry<String, Field> entry : fieldMap.entrySet()) {
            Field field = entry.getValue();
            // 无标记
            if (!field.isAnnotationPresent(AnDict.class)) {
                continue;
            }
            // 设置文本
            if (field.getType() == String.class) {
                // 字典字符串
                AnDict anDict = field.getAnnotation(AnDict.class);
                String ref = anDict.ref();
                if (ref == null || !fieldMap.containsKey(ref)) {
                    continue;
                }
                // 获取映射编码
                Field refField = fieldMap.get(ref);
                Object refObj;
                try {
                    refObj = refField.get(bean);
                } catch (Exception e) {
                    e.printStackTrace();
                    refObj = null;
                }

                if (refObj == null || !(refObj instanceof Integer)) {
                    continue;
                }

                // 设置字典文本
                Integer dataCode = (Integer) refObj;
                String dictCode = anDict.dict().getCode();
                String dataText = null;

                if (!dictMap.containsKey(dictCode)) {
                    continue;
                }

                ArrayList<DataDictionaryItem> dictItems = dictMap.get(dictCode);
                if (dictItems == null) {
                    break;
                }
                // 查找字典数据
                for (DataDictionaryItem dictItem : dictItems) {
                    if (dictCode.equals(dictItem.getDictCode())
                            && dataCode.intValue() == dictItem.getDataCode().intValue()) {
                        dataText = dictItem.getDataText();
                        break;
                    }
                }

                // 不存在缓存字典时，查找删除的字典
                if (DataUtil.invalid(dataText)) {
                    for (DataDictionaryItem dictItem : deletedList) {
                        if (dictCode.equals(dictItem.getDictCode())
                                && dataCode.intValue() == dictItem.getDataCode().intValue()) {
                            dataText = dictItem.getDataText();
                            break;
                        }
                    }
                }

                // 设置字典数据
                if (dataText != null) {
                    try {
                        field.set(bean, dataText);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                continue;
            }

            // 自定义对象，进一步赋值
            Object object;
            try {
                object = field.get(bean);
            } catch (Exception e) {
                object = null;
            }
            if (object != null) {
                if (object instanceof BaseBean) {
                    HashMap<String, Field> fieldTypeMap = ReflectUtil.getFieldMapByClass(field.getType());
                    resetDataText4Bean(dictMap, deletedList, fieldTypeMap, object);
                }
            }
        }
    }

    /**
     * 获取某个字典数据值
     *
     * @param eDictCode 字典编码枚举
     * @param dataCode  字典编码值
     * @return
     * @author LiCongLu
     * @date 2020-02-11 14:18
     */
    public DataDictionaryItem getDataDictionaryItem(EDictCode eDictCode, Integer dataCode) {
        return getDataDictionaryItem(eDictCode.getCode(), dataCode);
    }

    /**
     * 获取某个字典数据值
     *
     * @param dictCode 字典编码
     * @param dataCode 字典编码值
     * @return
     * @author LiCongLu
     * @date 2020-02-10 14:04
     */
    public DataDictionaryItem getDataDictionaryItem(String dictCode, Integer dataCode) {
        if (dictCode == null || dataCode == null) {
            return null;
        }

        // 缓存字典
        HashMap<String, ArrayList<DataDictionaryItem>> dictMap = mapDictionary();
        if (dictMap.containsKey(dictCode)) {
            ArrayList<DataDictionaryItem> dictItems = dictMap.get(dictCode);
            if (dictItems != null) {
                // 查找字典数据
                for (DataDictionaryItem dictItem : dictItems) {
                    if (dictCode.equals(dictItem.getDictCode())
                            && dictItem.getDictCode() != null
                            && dataCode.intValue() == dictItem.getDataCode().intValue()) {
                        return BeanUtil.copy2Bean(dictItem, new DataDictionaryItem());
                    }
                }
            }
        }

        // 被删除字典
        ArrayList<DataDictionaryItem> deletedList = deletedDictionary();
        if (DataUtil.valid(deletedList)) {
            for (DataDictionaryItem dictItem : deletedList) {
                if (dictCode.equals(dictItem.getDictCode())
                        && dictItem.getDictCode() != null
                        && dataCode.intValue() == dictItem.getDataCode().intValue()) {
                    return BeanUtil.copy2Bean(dictItem, new DataDictionaryItem());
                }
            }
        }

        return null;
    }


    /**
     * 获取某个类型的字典数据
     *
     * @param eDictCode 字典编码枚举
     * @return
     * @author LiCongLu
     * @date 2020-02-11 14:20
     */
    public ArrayList<DataDictionaryItem> listDataDictionaryItem(EDictCode eDictCode) {
        return listDataDictionaryItem(eDictCode.getCode());
    }

    /**
     * 获取某个类型的字典数据
     *
     * @param dictCode 字典编码
     * @return
     * @author LiCongLu
     * @date 2020-02-11 14:16
     */
    public ArrayList<DataDictionaryItem> listDataDictionaryItem(String dictCode) {
        if (dictCode == null) {
            return null;
        }

        // 复制新的集合
        ArrayList<DataDictionaryItem> dataItems = new ArrayList<>();
        HashMap<String, ArrayList<DataDictionaryItem>> dictMap = mapDictionary();
        if (dictMap.containsKey(dictCode)) {
            ArrayList<DataDictionaryItem> dictItems = dictMap.get(dictCode);
            if (dictItems != null) {
                // 查找字典数据
                for (DataDictionaryItem dictItem : dictItems) {
                    if (dictCode.equals(dictItem.getDictCode())) {
                        dataItems.add(BeanUtil.copy2Bean(dictItem, new DataDictionaryItem()));
                    }
                }
            }
        }
        return dataItems;
    }

    /**
     * 获取某个字典文本值
     * 默认返回NULL
     *
     * @param dictCode 字典编码
     * @param dataCode 字典编码值
     * @return
     * @author GuanKui
     * @date 2020/2/25  8:48
     */
    public String getDataText(String dictCode, Integer dataCode) {
        DataDictionaryItem dictItem = getDataDictionaryItem(dictCode, dataCode);
        if (dictItem != null) {
            return dictItem.getDataText();
        }
        return null;
    }

    /**
     * 按照字典编码获取字典文本值
     * 默认返回NULL
     *
     * @param eDictCode 字典
     * @param dataCode  数据编码值
     * @return
     * @author LiCongLu
     * @date 2020-02-25 10:26
     */
    public String getDataText(EDictCode eDictCode, Integer dataCode) {
        DataDictionaryItem dictItem = getDataDictionaryItem(eDictCode.getCode(), dataCode);
        if (dictItem != null) {
            return dictItem.getDataText();
        }
        return null;
    }
}
